<template>
  <Teleport :to="appendTo" :disabled="appendDisabled">
    <transition name="fade">
      <div class="modal_layout" ref="modalRef" v-if="visible">
        <div class="modal_layout_mask" :class="{ pointer: clickMaskClose }" @click.stop="() => handleNMask()">
          <div @click.stop v-bind="attr" :class="[`modal_content_default ${customClass}`]">
            <slot></slot>
          </div>
        </div>
      </div>
    </transition>
  </Teleport>
</template>
<script setup lang="ts">
  import { useAttrs, ref } from 'vue'
  const attr = useAttrs()
  const props = withDefaults(
    defineProps<{
      modelValue?: boolean
      appendTo?: string | HTMLElement // 挂载的元素
      customClass?: string // 自定义样式
      clickMaskClose?: boolean // 点击遮罩层关闭
      appendDisabled?: boolean // 是否禁用传送到指定元素
    }>(),
    {
      appendTo: 'body',
      modalValue: false,
      customClass: '',
      clickMaskClose: true,
      appendDisabled: false
    }
  )
  const emit = defineEmits(['update:modelValue'])
  const modalRef = ref<HTMLElement | null>(null)
  const visible = ref<boolean>(false)
  const open = () => {
    visible.value = true
  }
  const close = () => {
    visible.value = false
    emit('update:modelValue', false)
  }
  const handleNMask = () => {
    if (props.clickMaskClose) {
      close()
    }
  }
  watch(
    () => props.modelValue,
    val => {
      visible.value = val
    },
    { immediate: true }
  )
  defineExpose({ open, close })
</script>
<style scoped lang="scss">
  .fade-enter-from,
  .fade-leave-to {
    opacity: 0;
  }
  .fade-enter-active {
    transition: opacity 0.5s ease;
  }
  .modal_layout {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    width: 100%;
    height: 100%;
    .modal_layout_mask {
      width: inherit;
      height: inherit;
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      align-content: flex-start;
      background: rgba(39, 47, 65, 0.3);
      .modal_content_default {
        min-width: 277px;
        min-height: 194px;
        border-radius: 20px;
        background: rgba(255, 255, 255, 1);
      }
    }
    .pointer {
      cursor: pointer;
    }
  }
</style>
